package com.wongoing.aop;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.wongoing.jwt.TokenManager;
import com.wongoing.jwt.JwtUserModel;
import com.wongoing.bus.util.Constants;
import com.wongoing.util.IpUtil;
import com.wongoing.util.ResourceUtil;


/**
 * 权限拦截器
 * 
 */
public class RestAuthInterceptor implements HandlerInterceptor {
	 
	private static final Logger logger = Logger.getLogger(RestAuthInterceptor.class);
	
	private List<String> excludeUrlsNoIPAndSignCheck;
	
	public List<String> getExcludeUrlsNoIPAndSignCheck() {
		return excludeUrlsNoIPAndSignCheck;
	}

	public void setExcludeUrlsNoIPAndSignCheck(List<String> excludeUrlsNoIPAndSignCheck) {
		this.excludeUrlsNoIPAndSignCheck = excludeUrlsNoIPAndSignCheck;
	}

	/**
	 * 在controller后拦截
	 */
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception exception) throws Exception {
	}

	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView modelAndView) throws Exception {
	}

	/**
	 * 在controller前拦截
	 */
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		
		String requestPath = ResourceUtil.getRequestPath(request);// 用户访问的资源地址
		String requestIp = IpUtil.getIpAddr(request);
		String requestPathAndGetParam = ResourceUtil.getRequestPathAndGetParam(request);
		String postParam = ResourceUtil.getPostParam(request);
		
		// 如果是预请求，则直接返回，不做业务处理（主要针对post）
		if("OPTIONS".equals(request.getMethod())) {
			return true;
		}
		
		// 如果在spring-mvc忽略列表 则跳过
		if (null != excludeUrlsNoIPAndSignCheck) {
			for(String str : excludeUrlsNoIPAndSignCheck){
				if(requestPath.contains(str)){
					//如果该请求不在拦截范围内，直接返回true
					logger.info("ip : " + requestIp + " 忽略列表,无需CHECK" + " - requestPath : " + requestPathAndGetParam + ", params :" + postParam);
					return true;
				}
			}
		}
		
		// 如果不是映射到方法直接不通过
        if (!(handler instanceof HandlerMethod)) {
        	logger.info("ip : " + requestIp + " 非法URL" + " - requestPath : " + requestPathAndGetParam + ", params :" + postParam);
        	response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }

		// 从header中得到token
		String reqToken = request.getHeader(Constants.AUTHORIZATION);
		if(StringUtils.isBlank(reqToken) || "null".equals(reqToken)){
			logger.info("ip : " + requestIp + " token 为空" + " - requestPath : " + requestPathAndGetParam + ", params :" + postParam);
			response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			return false;
		}

        // 验证token 加密是否合法
		String userName = null;
		try{
			userName = TokenManager.getInstance().checkToken(reqToken);
		}catch(io.jsonwebtoken.SignatureException ex) {
			logger.error(ex.getMessage());
		}
        if (StringUtils.isBlank(userName)) {
        	logger.info("ip : " + requestIp + " token 不合法" + " - requestPath : " + requestPathAndGetParam + ", params :" + postParam);
			response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			return false;
        }
        
        // 验证用户 
        String token = TokenManager.getInstance().getToken(userName);
        if (StringUtils.isBlank(token) && !reqToken.equals(token)) {
        	logger.info("ip : " + requestIp + " token 无效" + " - requestPath : " + requestPathAndGetParam + ", params :" + postParam);
			response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			return false;
        }
        
        // 验证token 有效期
        JwtUserModel userModel = TokenManager.getInstance().getUserModel(userName);
        System.out.println(userModel.getExp().getTime());
        System.out.println(System.currentTimeMillis());
        if(userModel.getExp().getTime() >= System.currentTimeMillis()){
        	
        	// 刷新 过期时间
        	TokenManager.getInstance().refreshExpDate(userName);
        	
        	// 如果token验证成功，将token对应的用户存在request中，便于之后注入
        	request.getSession().setAttribute(Constants.CURRENT_USER_ID, userModel);
        	// TODO 每次请求返回新的token
//        	response.setHeader(Globals.AUTHORIZATION, newToken);
        	logger.info("ip : " + requestIp  + " - requestPath : " + requestPathAndGetParam + ", params :" + postParam);
        	return true;
        	
        } else if(userModel.getExp().getTime() < System.currentTimeMillis()) {
        	
        	logger.info("ip : " + requestIp + " token 过期" + " - requestPath : " + requestPathAndGetParam + ", params :" + postParam);
			response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			return false;
        }

        logger.info("ip : " + requestIp + " 没有访问权限" + " - requestPath : " + requestPathAndGetParam + ", params :" + postParam);
        
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        return false;
	}

}
